# instalacao do qt, e outras infos em
# http://cran.r-project.org/web/packages/qtbase/index.html
library (qtbase)
source("./Desktop/Unicamp/MO444/word-prediction-mo444/trab-funcoes-fernando.r")



guessNextWord <- function (text) {
  suggestionTable <- getSuggestionList(text)
  #pega os 3 melhores
  max = which.max(suggestionTable)
  max1 = names(max)[1]
  suggestionTable[max] <- NULL
  max = which.max(suggestionTable)
  max2 = names(max)[1]
  suggestionTable[max] <- NULL
  max = which.max(suggestionTable)
  max3 = names(max)[1]
  suggestionTable[max] <- NULL
  return (c(max1, max2, max3))
}

getSuggestionList <-function (text) {
  text = tolower(x=text);
  textSplitted = unlist(strsplit(text, split=" "));
  suggestionTable = vector(mode="list")
  if (length(textSplitted) >= 1) {
    pattern = paste("^", textSplitted[length(textSplitted)], " ", sep="")
    bigrams = grep(pattern, rownames(bigramTable), value = TRUE)
    if (length(bigrams) > 0) {
      for (i in 1:length(bigrams)){
        suggestion = tail(strsplit(bigrams[i],split=" ")[[1]],1)  
        if (suggestion %in% names(suggestionTable)) {suggestionTable[[suggestion]] = suggestionTable[[suggestion]] + bigramTable[bigrams[i],]}
        else {suggestionTable[[suggestion]] = 1}
      }
    }
  }
  
  if (length(textSplitted) >= 2) {
    pattern = paste("^", textSplitted[length(textSplitted)-1], " ", sep="")
    trigrams = grep(pattern, rownames(trigramTable), value = TRUE)
    if (length(trigrams) > 0) {
      for (i in 1:length(trigrams)){
        suggestion = tail(strsplit(trigrams[i],split=" ")[[1]],1)  
        if (suggestion %in% names(suggestionTable)) {suggestionTable[[suggestion]] = suggestionTable[[suggestion]] + trigramTable[trigrams[i],]}
        else {suggestionTable[[suggestion]] = 1}
      }
    }
  }
  if (length(textSplitted) >= 3) {
    pattern = paste("^", textSplitted[length(textSplitted)-2], " ", sep="")
    quadrigrams = grep(pattern, rownames(quadgramTable), value = TRUE)    
    if (length(quadrigrams) > 0) {
      for (i in 1:length(quadrigrams)){
        suggestion = tail(strsplit(quadrigrams[i],split=" ")[[1]],1)  
        if (suggestion %in% names(suggestionTable)) {suggestionTable[[suggestion]] = suggestionTable[[suggestion]] + quadgramTable[quadrigrams[i],]}
        else {suggestionTable[[suggestion]] = 1}
      }
    }
  }
  return (suggestionTable)
}

fixCurrentWord <- function (text, currentWord) {
  suggestionList = getSuggestionList(text)
  for (i in 1:length(names(suggestionList))) {
    dist = adist (currentWord, names(suggestionList)[i])
    dist = 1/dist*10
    #usa a distancia de Levenshtein para computar a distancia entre duas palavras
    suggestionList[[i]] <- dist
  }
  #pega os 3 melhores
  max = which.max(suggestionList)
  max1 = names(max)[1]
  suggestionList[max] <- NULL
  max = which.max(suggestionList)
  max2 = names(max)[1]
  suggestionList[max] <- NULL
  max = which.max(suggestionList)
  max3 = names(max)[1]
  suggestionList[max] <- NULL
  return (c(max1, max2, max3))
}



#pede sugestoes para o classificador
getSuggestions <- function(ignoreLastWord=FALSE){
  x = strsplit(textedit$toPlainText(), "[[:space:]]+")
  if (ignoreLastWord == FALSE) {
    last <- tail(x[[1]], n=3)
    str <- paste(last, collapse=' ')
    class = guessNextWord(str)
    button1$setText(class[1])
    button2$setText(class[2])
    button3$setText(class[3])
    print(class)
  } else {
    last <- tail(x[[1]], n=4)
    first <- head(last,-1)
    str <- paste(tail(last, n=1), collapse=' ')
    str1 <- paste(first, collapse=' ')
    if (length(last) > 0) {
      class = fixCurrentWord(str1, str)
      button1$setText(class[1])
      button2$setText(class[2])
      button3$setText(class[3])
      print(class)
    }
  }
  resetShortcuts()
}
#treina os dados fornecidos
trainText <- function(text="") {
  if(text %in% "") {
    return ()
  }
  write(text, "./Desktop/Unicamp/MO444/word-prediction-mo444/lucas/temp.txt")
  tempCorpus = Corpus(DirSource(directory='./Desktop/Unicamp/MO444/word-prediction-mo444/lucas', pattern="temp.txt"));
  tempCorpus = tm_map(x=tempCorpus, tolower);
  tempCorpus = tm_map(x=tempCorpus, removeNumbers);
  tempDictionary = TermDocumentMatrix(x=tempCorpus, control = list(tokenize = WordTokenizer));
  tempBigramTable = TermDocumentMatrix(x=tempCorpus, control = list(tokenize = BigramTokenizer));
  tempTrigramTable = TermDocumentMatrix(x=tempCorpus, control = list(tokenize = TrigramTokenizer));
  tempQuadgramTable = TermDocumentMatrix(x=tempCorpus, control = list(tokenize = QuadgramTokenizer));
  updateDataSet(tempDictionary, tempBigramTable, tempTrigramTable, tempQuadgramTable)
  textedit$setPlainText("")  
}


#atualiza o dataset com os novos dados
updateDataSet <- function(newDict, newBigram, newTrigram, newQuadgram) {
  #usa o tm_combine para combinar term document matrix
  dictTDM <<- c(dictTDM, newDict, recursive=TRUE)
  bigramTDM <<- c(bigramTDM, newBigram, recursive=TRUE)
  trigramTDM <<- c(trigramTDM, newTrigram, recursive=TRUE)
  quadgramTDM <<- c(quadgramTDM, newQuadgram, recursive=TRUE)
  #atualiza as tabelas
  dictionary <<- as.matrix(dictTDM)
  bigramTable <<- as.matrix(bigramTDM)
  trigramTable <<- as.matrix(trigramTDM)
  quadgramTable <<- as.matrix(quadgramTDM)
  #recalcula os ngrams
  bigram <<- gramSimplifier(bigramTable,2)
  trigram <<- gramSimplifier(trigramTable,3)
  quadgram <<- gramSimplifier(quadgramTable,4)
}
#checa se deve substituir a ultima palavra, ou inserir uma nova dependendo se o ultimo char e um espaco ou nao.
predictWord <-function(word) {
  x = strsplit(textedit$toPlainText(), split='')
  if (length(x[[1]]) == 0){
    insertNewWord(word)
  } else {
    x = x[[1]][length(x[[1]])] 
    #se o ultimo char for um espaco
    if(x %in% " "|| x %in% "\n"){
      insertNewWord(word)
    } else if (x %in% "."|| x %in% "," || x %in% ";" || x %in% ":") {
      insertNewWord(" ")
    } else {
      correctLastWord(word)
    }
  }
}
#insere uma palavra ao final do texto do campo
insertNewWord <- function(newWord) {
  #textedit$setPlainText(paste(textedit$toPlainText(), newWord, " ", sep=" ")) 
  tmpCursor = textedit$textCursor();
  tmpCursor$insertText(paste(newWord," ", sep="")) 
  tmpCursor$movePosition(Qt$QTextCursor$End, Qt$QTextCursor$MoveAnchor, 1);
  textedit$setTextCursor(tmpCursor)
}
#substitui a ultima palavra do campo de texto pelo parametro
correctLastWord <- function(newWord) {
  x = strsplit(textedit$toPlainText(), "[[:space:]]+")
  x[[1]][length(x[[1]])] <- paste(newWord, " ",sep="")
  textedit$setPlainText(paste(x[[1]], collapse=' '))
  tmpCursor = textedit$textCursor();
  tmpCursor$movePosition(Qt$QTextCursor$End, Qt$QTextCursor$MoveAnchor, 1);
  textedit$setTextCursor(tmpCursor)
}
#action disparada toda vez que o texto eh alterado
textChanged <- function() {
  x = textedit$toPlainText()
  if ("" %in% x) {
    return ()
  }
  x = strsplit(x, split='')
  char = x[[1]][length(x[[1]])]
  if(char %in% " "|| char %in% "\n"){
    getSuggestions(ignoreLastWord=FALSE)
  } else if (char %in% "."|| char %in% "," || char %in% ";" || char %in% ":") {
    insertNewWord("")
  } else {
    getSuggestions(ignoreLastWord=TRUE)
  }
}
#variaveis globais da interface
textedit <- Qt$QPlainTextEdit()
widget <- Qt$QWidget()
button1 <- Qt$QPushButton("Palavra1")
button2 <- Qt$QPushButton("Palavra2")
button3 <- Qt$QPushButton("Palavra3")
window <- Qt$QMainWindow()
#carrega a interface, nao exibe. chamar apenas uma vez.
loadInterface <- function () { 
  #container
  widget$setFixedWidth(600)
  widget$setFixedHeight(240)
  #layout
  layout <- Qt$QGridLayout(widget)
  #campo de texto
  textedit$setFixedWidth(580)
  textedit$setFixedHeight(170)
  textedit$updateGeometry()
  layout$addWidget(textedit, 0, 0)
  qconnect(textedit, "textChanged", textChanged)
  #botao1
  button1$setShortcutEnabled(TRUE)
  qconnect(button1, "pressed", function() predictWord(button1$text))
  layout$addWidget(button1, 1, 0)
  #botao2
  button2$setShortcutEnabled(TRUE)
  qconnect(button2, "pressed",function() predictWord(button2$text))
  layout$addWidget(button2, 1, 1)
  #botao3
  button3$setShortcutEnabled(TRUE)
  qconnect(button3, "pressed", function() predictWord(button3$text))
  layout$addWidget(button3, 1, 2)
  resetShortcuts()
  #janela
  window$setWindowTitle("Word Predictor")
  window$setCentralWidget(widget)
  #menu
  menuBar <- window$menuBar()
  fileMenu <- Qt$QMenu("File")
  helpMenu <- Qt$QMenu("Help")
  clearMenuAction <- Qt$QAction("Clear Text", fileMenu)
  trainMenuAction <- Qt$QAction("Train Data", fileMenu)
  quitMenuAction <- Qt$QAction("Quit", fileMenu)
  aboutMenuAction <- Qt$QAction("About", helpMenu)
  qconnect(clearMenuAction, "triggered", function() textedit$setPlainText(""))
  qconnect(trainMenuAction, "triggered", function() trainText(textedit$toPlainText()))
  qconnect(quitMenuAction, "triggered", function() window$close())
  fileMenu$addAction(clearMenuAction)
  fileMenu$addAction(trainMenuAction)
  fileMenu$addSeparator()
  fileMenu$addAction(quitMenuAction)
  helpMenu$addAction(aboutMenuAction)
  menuBar$addMenu(fileMenu)
  menuBar$addMenu(helpMenu)
}
#exibe o aplicativo.
launchApp <- function () {
  #exibe a janela
  window$show()
}
#reseta os atalhos dos botoes
resetShortcuts <- function () {
  keySeq <- Qt$QKeySequence("Alt+1")
  button1$setShortcut(keySeq)
  keySeq <- Qt$QKeySequence("Alt+2")
  button2$setShortcut(keySeq)
  keySeq <- Qt$QKeySequence("Alt+3")
  button3$setShortcut(keySeq)
}